00-面试查漏补缺

2024.3.13

Handler

  • sendMessage
  • post
    • 有callback的message
    • looper循环执行
  • sendMessage
    • 发送自定义的message
    • 可以没有callback
    • 可以有what、obj去和接收者传递消息

Message源码(仅public)

  • Message的获取
    • Handler包装的runnable
    • new Message()
    • obtain() 推荐,Message中的recycle方法会回收不用的Message,obtain的时候如果消息池不空,可以服用消息池
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
public final class Message implements Parcelable {
/**
* User-defined message code so that the recipient can identify
* what this message is about. Each {@link Handler} has its own name-space
* for message codes, so you do not need to worry about yours conflicting
* with other handlers.
*/
public int what;

/**
* arg1 and arg2 are lower-cost alternatives to using
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
public int arg1;

/**
* arg1 and arg2 are lower-cost alternatives to using
* {@link #setData(Bundle) setData()} if you only need to store a
* few integer values.
*/
public int arg2;

/**
* An arbitrary object to send to the recipient. When using
* {@link Messenger} to send the message across processes this can only
* be non-null if it contains a Parcelable of a framework class (not one
* implemented by the application). For other data transfer use
* {@link #setData}.
*
* <p>Note that Parcelable objects here are not supported prior to
* the {@link android.os.Build.VERSION_CODES#FROYO} release.
*/
public Object obj;
@UnsupportedAppUsage
/*package*/ int flags;

/**
* The targeted delivery time of this message. The time-base is
* {@link SystemClock#uptimeMillis}.
* @hide Only for use within the tests.
*/
@UnsupportedAppUsage
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public long when;


/** @hide */
public static final Object sPoolSync = new Object();

/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}

/**
* Same as {@link #obtain()}, but copies the values of an existing
* message (including its target) into the new one.
* @param orig Original message to copy.
* @return A Message object from the global pool.
*/
public static Message obtain(Message orig) {
Message m = obtain();
m.what = orig.what;
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.obj;
m.replyTo = orig.replyTo;
m.sendingUid = orig.sendingUid;
m.workSourceUid = orig.workSourceUid;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;

return m;
}

/**
* Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
* @param h Handler to assign to the returned Message object's <em>target</em> member.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;

return m;
}

/**
* Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
* the Message that is returned.
* @param h Handler to assign to the returned Message object's <em>target</em> member.
* @param callback Runnable that will execute when the message is handled.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;

return m;
}

/**
* Same as {@link #obtain()}, but sets the values for both <em>target</em> and
* <em>what</em> members on the Message.
* @param h Value to assign to the <em>target</em> member.
* @param what Value to assign to the <em>what</em> member.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what) {
Message m = obtain();
m.target = h;
m.what = what;

return m;
}

/**
* Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em>
* members.
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param obj The <em>object</em> method to set.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what, Object obj) {
Message m = obtain();
m.target = h;
m.what = what;
m.obj = obj;

return m;
}

/**
* Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
* <em>arg1</em>, and <em>arg2</em> members.
*
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param arg1 The <em>arg1</em> value to set.
* @param arg2 The <em>arg2</em> value to set.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what, int arg1, int arg2) {
Message m = obtain();
m.target = h;
m.what = what;
m.arg1 = arg1;
m.arg2 = arg2;

return m;
}

/**
* Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>,
* <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members.
*
* @param h The <em>target</em> value to set.
* @param what The <em>what</em> value to set.
* @param arg1 The <em>arg1</em> value to set.
* @param arg2 The <em>arg2</em> value to set.
* @param obj The <em>obj</em> value to set.
* @return A Message object from the global pool.
*/
public static Message obtain(Handler h, int what,
int arg1, int arg2, Object obj) {
Message m = obtain();
m.target = h;
m.what = what;
m.arg1 = arg1;
m.arg2 = arg2;
m.obj = obj;

return m;
}

/** @hide */
public static void updateCheckRecycle(int targetSdkVersion) {
if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
gCheckRecycle = false;
}
}

/**
* Return a Message instance to the global pool.
* <p>
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
* </p>
*/
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
/**
* Return the targeted delivery time of this message, in milliseconds.
*/
public long getWhen() {
return when;
}

public void setTarget(Handler target) {
this.target = target;
}

/**
* Retrieve the {@link android.os.Handler Handler} implementation that
* will receive this message. The object must implement
* {@link android.os.Handler#handleMessage(android.os.Message)
* Handler.handleMessage()}. Each Handler has its own name-space for
* message codes, so you do not need to
* worry about yours conflicting with other handlers.
*/
public Handler getTarget() {
return target;
}

/**
* Retrieve callback object that will execute when this message is handled.
* This object must implement Runnable. This is called by
* the <em>target</em> {@link Handler} that is receiving this Message to
* dispatch it. If
* not set, the message will be dispatched to the receiving Handler's
* {@link Handler#handleMessage(Message)}.
*/
public Runnable getCallback() {
return callback;
}

/** @hide */
@UnsupportedAppUsage
public Message setCallback(Runnable r) {
callback = r;
return this;
}

/**
* Obtains a Bundle of arbitrary data associated with this
* event, lazily creating it if necessary. Set this value by calling
* {@link #setData(Bundle)}. Note that when transferring data across
* processes via {@link Messenger}, you will need to set your ClassLoader
* on the Bundle via {@link Bundle#setClassLoader(ClassLoader)
* Bundle.setClassLoader()} so that it can instantiate your objects when
* you retrieve them.
* @see #peekData()
* @see #setData(Bundle)
*/
public Bundle getData() {
if (data == null) {
data = new Bundle();
}

return data;
}

/**
* Like getData(), but does not lazily create the Bundle. A null
* is returned if the Bundle does not already exist. See
* {@link #getData} for further information on this.
* @see #getData()
* @see #setData(Bundle)
*/
public Bundle peekData() {
return data;
}

/**
* Sets a Bundle of arbitrary data values. Use arg1 and arg2 members
* as a lower cost way to send a few simple integer values, if you can.
* @see #getData()
* @see #peekData()
*/
public void setData(Bundle data) {
this.data = data;
}

/**
* Chainable setter for {@link #what}
*
* @hide
*/
public Message setWhat(int what) {
this.what = what;
return this;
}

/**
* Sends this Message to the Handler specified by {@link #getTarget}.
* Throws a null pointer exception if this field has not been set.
*/
public void sendToTarget() {
target.sendMessage(this);
}

/**
* Returns true if the message is asynchronous, meaning that it is not
* subject to {@link Looper} synchronization barriers.
*
* @return True if the message is asynchronous.
*
* @see #setAsynchronous(boolean)
*/
public boolean isAsynchronous() {
return (flags & FLAG_ASYNCHRONOUS) != 0;
}

/**
* Sets whether the message is asynchronous, meaning that it is not
* subject to {@link Looper} synchronization barriers.
* <p>
* Certain operations, such as view invalidation, may introduce synchronization
* barriers into the {@link Looper}'s message queue to prevent subsequent messages
* from being delivered until some condition is met. In the case of view invalidation,
* messages which are posted after a call to {@link android.view.View#invalidate}
* are suspended by means of a synchronization barrier until the next frame is
* ready to be drawn. The synchronization barrier ensures that the invalidation
* request is completely handled before resuming.
* </p><p>
* Asynchronous messages are exempt from synchronization barriers. They typically
* represent interrupts, input events, and other signals that must be handled independently
* even while other work has been suspended.
* </p><p>
* Note that asynchronous messages may be delivered out of order with respect to
* synchronous messages although they are always delivered in order among themselves.
* If the relative order of these messages matters then they probably should not be
* asynchronous in the first place. Use with caution.
* </p>
*
* @param async True if the message is asynchronous.
*
* @see #isAsynchronous()
*/
public void setAsynchronous(boolean async) {
if (async) {
flags |= FLAG_ASYNCHRONOUS;
} else {
flags &= ~FLAG_ASYNCHRONOUS;
}
}

/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
*/
public Message() {
}
}

Looper每次循环在做什么

  • 取消息
  • 分发消息
1
2
3
4
5
6
7
8
9
10
11
12
@SuppressWarnings({"UnusedTokenOfOriginalCallingIdentity",
"ClearIdentityCallNotFollowedByTryFinally"})
private static boolean loopOnce(final Looper me,
final long ident, final int thresholdOverride) {
Message msg = me.mQueue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return false;
}
msg.target.dispatchMessage(msg);
// 省略部分大概是和observer交互还有打log
}

Handler.dispatchMessage

  • 有callback就执行callback
  • 没有则通过mCallback对象或者子类重写handleMessage分发消息。
1
2
3
4
5
6
7
8
9
10
11
12
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}

MessageQueue

enqueue消息的操作

  • 按照when大小入队
  • 如果不是异步消息且队初始为空或队列中消息为异步消息或消息没有target,则wake对方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}

synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}

msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}

// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}

取消息的操作

  • 取消息
    • 如果有消息
      • ready了,就返回
      • 没ready,阻塞等着通过nativePollOnce,如果有人enqueue,则会通过nativeWake唤醒
    • 没有消息了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@UnsupportedAppUsage
Message next() {
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}

nativePollOnce(ptr, nextPollTimeoutMillis);
// 如果消息还没有ready,阻塞等待一段时间
// nextPollTimeoutMillis的计算在上一次循环,看下面的代码

synchronized (this) { // 只有一个线程能拿消息
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
// nextPollTimeoutMillis的计算
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg; // 拿到消息,返回
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
}
}
}

Handler实战

  • 普通进程使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler(Looper.myLooper()) {
public void handleMessage(Message msg) {
//处理即将发送过来的消息
System.out.println("thread id="+Thread.currentThread().getId());
}
}
Looper.loop();
}
}
// 外部开启线程、获取handler,post/sendMessage
  • HandlerThread
1
2
3
4
HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start(); // 创建HandlerThread
Handler handler = new Handler(handlerThread.getLooper());
// 拿到HandlerThread的Looper,创建handler
  • Looper退出
    • quit : 删除所有消息,包括正在运行的
    • quitSafely() : 删除未运行的消息

AOT和JIT的对比

AOT和JIT的对比

System.arraycopy

Performance of System.arraycopy() vs. Arrays.copyOf()

arraycopy是native方法,用c实现的,可能是memcpy等方法实现的,效率因平台而不同

ANR(App Not Responding)

  • 哪些场景导致ANR
    • Service Timeout:Service在特定的时间内无法处理完成
    • BroadcastQueue Timeout:BroadcastReceiver在特定时间内无法处理完成
    • ContentProvider Timeout:内容提供者执行超时
    • inputDispatching Timeout: 按键或触摸事件在特定时间内无响应。

ServiceANR

realStartServiceLocked()->bumpServiceExecutingLocked()->scheduleServiceTimeoutLocked()

在Service启动过程中,scheduleServiceTimeoutLocked通过native层的handler发送了DelayedMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
// 在serviceDoneExecutingLocked中会remove该SERVICE_TIMEOUT_MSG消息,
// 当超时后仍没有remove SERVICE_TIMEOUT_MSG消息,则执行ActiveServices. serviceTimeout()方法;
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
// 前台进程中执行Service,SERVICE_TIMEOUT=20s;后台进程中执行Service,SERVICE_BACKGROUND_TIMEOUT=200s
}

在Service的OnCreate结束后或启动过程抛出异常,调用serviceDoneExecutingLocked删除消息

1
2
3
4
if (r.app.executingServices.size() == 0) {
if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
"No more executingServices of " + r.shortName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);

在service的oncreate阶段不要执行过重的任务

InputDispatchingANR

在分派输入事件时,InputDispatcher会检查当前是否有聚焦的窗口和应用,获取超时时间,如果当前时间大于超时时间,就弹出ANR

Activity.onCreate执行耗时操作,不管用户如何操作都不会发生ANR,因为输入事件相关监听机制还没有建立起来;InputChannel通道还没有建立

应对方案

  • 耗时操作子线程处理,结束后切回主线程更新ui

Logs

除了主体逻辑,发生ANR时还会输出各种类别的日志:
event log:通过检索”am_anr”关键字,可以找到发生ANR的应用
main log:通过检索”ANR in “关键字,可以找到ANR的信息,日志的上下文会包含CPU的使用情况
dropbox:通过检索”anr”类型,可以找到ANR的信息
traces:发生ANR时,各进程的函数调用栈信息

看完这篇 Android ANR 分析,就可以和面试官装逼了!

Activity/Fragment Lifecycle

Activity

Activity Lifecycle

  • onSaveInstanceState() 与 onRestoreIntanceState()

    • 不属于生命周期
    • onSaveInstanceState保存临时性的状态
    • onRestoreIntanceState恢复临时性的状态
    • 调用时机
      • 异常终止的时候才会调用
      • 资源内存不足导致低优先级的 Activity 被杀死
        • 高优先级:前台Activity
        • 中优先级:可见且非前台
        • 低优先级:后台Activity
      • 资源相关的系统配置发生改变导致Activity被杀死并重新创建
      • 旋转屏幕
    • 旋转屏幕时
      • 旧Activity:puase->onSaveInstanceState->stop->destory
      • 新Activity:create->start->onRestoreInstanceState->onresume
        • onCreate中也能取到onSaveInstanceState,但是官方建议使用onRestoreInstanceState恢复数据
  • onCreate: 创建中,

  • onStart:可见但不可交互

  • onResume:可见可交互

  • onPause:可见不可交互

    • 其他应用需要内存,就会Kill进程,下次回来时,进入onCreate
  • onStop:不可见

    • 其他应用需要内存,就会Kill进程,下次回来时,进入onCreate
    • 一般情况下,下次回来时,调用onRestart然后onCreate
  • onDestroy:销毁

其他Activity进入前台,当前Activity就会onPause,onStop。如果手快一点,在当前Activity没有彻底消失时就关闭下一个Activity,就不会进入onStop

Fragment

Fragment Lifecycle

AAR

  • 也是一种打包的zip文件
  • 远程aar和本地arr

R文件

  • 资源id
  • 编译时会生成resources.arsc,包含id到实际值的映射
  • 都是static final,可以被内联
    • application module被内联了
  • 部分不是final,是static的
    • library module的R文件中的常量没有被内联
    • aar没有被内联
  • 压缩
    • AGP 4.1.0打包时,在release包中已经彻底优化掉R文件
    • 混淆,缩短id等标识符长度
    • 删除不需要的资源
    • 从应用及其库依赖中检测并安全地移除不使用的类、字段、方法和属性

HTTP断点续传

各种生命周期

sql事务

view绘制原理

activity启动模式

这里的都不太会

2024.3.17美团笔试

面向对象的各种概念

  • 单一职责

编译原理相关知识

  • 文法自动机相关知识

2024.3.19美团二面

Service生命周期

  • 非绑定式
    • -(首次startService)->onCreate()
    • -(非首次startService)->onStartCommand()
    • -(stopService/stopSelf)->onDestroy()
  • 绑定式
    • -(首次bindService)->onCreate()
    • -(非首次bindService)->onBind()
    • -(unbindService/stopSelf)->onUnbind()->onDestroy()

Activity与Service交互信息

  • 非绑定式
    • startService时用Intent传递
  • 绑定式
    • 创建ServiceConnect对象,获取IBinder
    • 通过IBinder交互
    • Service中创建对象,继承Binder

前台Service

  • 前台服务,一般用来创建notification,且不可移除的通知
  • onCreate时通过startForeground创建通知
  • 通过stopForeground停止前台服务

动态广播的使用

sendBroadCast

接受

创建IntentFilter
创建BroadcastReceiver
registerReceiver
unregistReceiver

  • 两个Activity之间传递消息

静态广播

创建接收器
在Manifest文件中注册,指定接收器类名和IntentFilter

  • 8.0后无法接受隐式广播(intent只指定action)
    • intent.setPackage(getPackageName()) // 接收方的包名
    • intent.addFlags(FLAG_RECEIVER_INCLUDE_BACKGROUND)

有序广播无序广播

  • 无序广播
    • 默认就是无序广播
    • 多个接收器同时接受
  • 有序广播
    • 接收器依照优先级依次接受广播
    • 通过context.sendOrderedBroadcast(intent, permission);发送
    • intentFilter.setPriority()
    • sendOrderedBoradcast
    • 在广播接收器中abortBroadcast会截断广播向低优先级的传递
    • setResultExtras和getResultExtras,上游接收器向下游发送消息
    • setResultData和getResultData,上游接收器向下游发送消息

本地广播全局广播

  • 本地广播:仅在app内部传播
    • 只能动态注册
    • LocalBroadCastReceiver(已废弃,需要手动添加依赖)
  • 全局广播:整个系统都能接受
    • 默认就是全局的

Java新技术(kotlin早已支持)

  • 密封类
    • 规定可以有哪些子类
1
2
public abstract sealed class Reference<T>
permits PhantomReference, SoftReference, WeakReference, FinalReference {

Hook技术

通过反射,将某些回调字段设置成一个代理对象,代理字段中对invoke进行hook

Xposed框架

通过替换/system/bin/app_process程序控制zygote进程,使app_process在启动过程中加载XposedBridge.jar,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持

  • posed自定义模块开发
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main implements IXposedHookLoadPackage { 
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (!loadPackageParam.packageName.equals("com.example.pengchengxiang.inputdemo")) {
return;
}

XposedBridge.log("Loaded app:" + loadPackageParam.packageName);
//Hook 类的方法
findAndHookMethod("className", loadPackageParam.classLoader, "methodNAme", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
}

@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
}
});
}
}
作者

Meow Meow Liu

发布于

2024-03-13

更新于

2024-09-13

许可协议

评论